package com.mine.async.jobexe;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mine.async.constants.DownloadConstant;
import com.mine.async.domain.pojo.DownloadJobBO;
import com.mine.async.domain.pojo.DownloadJobItemBO;
import com.mine.async.enums.JobSelectResultEnum;
import com.mine.async.enums.JobStatusEnum;
import com.mine.async.enums.JobTypeEnum;
import com.mine.async.service.IDownloadJobItemService;
import com.mine.async.service.IDownloadJobService;
import com.mine.async.utils.DownloadCalcUtil;
import com.mine.async.utils.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Component
@Slf4j
public class DownloadJobHandler {

    @Autowired
    private IDownloadJobService downloadJobService;

    @Autowired
    private IDownloadJobItemService downloadJobItemService;

    private final static String localFilePath = "e:/down";

    String createInitJob(PageQuery pageQuery) {
        if (StrUtil.isNotEmpty(pageQuery.getRetryJobNo())) {
            DownloadJobBO retryJobBO = downloadJobService.getByJobNo(pageQuery.getRetryJobNo());
            if (retryJobBO == null) {
                throw new RuntimeException("不存在的重试jobNo" + pageQuery.getRetryJobNo());
            }
            DownloadJobBO jobBOUp = new DownloadJobBO();
            jobBOUp.setId(retryJobBO.getId());
            jobBOUp.setJobStatus(JobStatusEnum.READY.getCode());
            jobBOUp.setJobRatio(0);
            jobBOUp.setFailRetryNum(retryJobBO.getFailRetryNum() == null ? 1 : retryJobBO.getFailRetryNum() + 1);
            downloadJobService.updateById(jobBOUp);
            return pageQuery.getRetryJobNo();
        }
        DownloadJobBO jobBO = new DownloadJobBO();
        jobBO.setJobStatus(JobStatusEnum.READY.getCode());
        jobBO.setJobNo(genJobNo());
        jobBO.setJobRatio(0);
        jobBO.setTypeCode(pageQuery.getTypeCode());
        jobBO.setTypeName(JobTypeEnum.getNameByCode(pageQuery.getTypeCode()));
        jobBO.setSelectParams(JSONObject.toJSONString(pageQuery));
        jobBO.setParamClassName(pageQuery.getParamClassName());
        jobBO.setBeanClassName(pageQuery.getBeanClassName());
        jobBO.setMethodName(pageQuery.getMethodName());
        jobBO.setRetryCount(pageQuery.getRetryCount());
        jobBO.setFailRetryFlag(pageQuery.getRetryFlag());
        downloadJobService.save(jobBO);
        return jobBO.getJobNo();
    }

    void beforeSelect(String jobNo, long eachLimit) {
        DownloadJobBO job = downloadJobService.getByJobNo(jobNo);
        if (ObjectUtil.isNotNull(job)) {
            DownloadJobBO jobUp = new DownloadJobBO();
            jobUp.setId(job.getId());
            jobUp.setEachLimit(eachLimit);
            jobUp.setJobStatus(JobStatusEnum.RUNING.getCode());
            jobUp.setDownloadStartTime(new Date());
            downloadJobService.updateById(jobUp);
        }
    }

    boolean afterSelectEach(String jobNo, String fileName, long currPageNo, long pageSize, List records, long totalCount, long eachStart) {
        DownloadJobBO job = downloadJobService.getByJobNo(jobNo);
        if (ObjectUtil.isNull(job)) return false;
        boolean fillSuccess = true;
        String failMsg = null;
        try {
            fillFileData(fileName, records, DownloadCalcUtil.getSelectedCount(currPageNo, pageSize, 0), JobTypeEnum.getByCode(job.getTypeCode()));
        } catch (Exception e) {
            log.error("填充excel文件数据错误", e);
            fillSuccess = false;
            failMsg = e.getMessage();
        }
        DownloadJobBO jobUp = new DownloadJobBO();
        jobUp.setId(job.getId());

        DownloadJobItemBO jobItemBO = new DownloadJobItemBO();
        jobItemBO.setJobId(job.getId());
        jobItemBO.setJobNo(job.getJobNo());
        jobItemBO.setSelectStartTime(new Date(eachStart));
        jobItemBO.setSelectEndTime(new Date());
        jobItemBO.setSelectTimes(System.currentTimeMillis() - eachStart);
        jobItemBO.setSelectTotal(records.size());
        jobItemBO.setSelectPageNo(currPageNo);
        jobItemBO.setSelectPageSize(pageSize);
        if (fillSuccess) {
            jobUp.setSelectNumTotal(getSelectNumTotal(job.getSelectNumTotal()));
            jobUp.setJobRatio(DownloadCalcUtil.calcDownloadRatio(currPageNo, pageSize, records.size(), totalCount));
            downloadJobService.updateById(jobUp);
            jobItemBO.setSelectNum(jobUp.getSelectNumTotal());
            jobItemBO.setSelectRatio(jobUp.getJobRatio());
            jobItemBO.setSelectResult(JobSelectResultEnum.SUCCESS.getCode());
            downloadJobItemService.save(jobItemBO);
        } else {
            jobUp.setJobStatus(JobStatusEnum.EXCEPTION.getCode());
            downloadJobService.updateById(jobUp);
            jobItemBO.setSelectNum(getSelectNumTotal(job.getSelectNumTotal()));
            jobItemBO.setSelectRatio(DownloadCalcUtil.calcDownloadRatio(currPageNo, pageSize, records.size(), totalCount));
            jobItemBO.setSelectResult(JobSelectResultEnum.FAIL.getCode());
            jobItemBO.setFailMsg(failMsg);
            downloadJobItemService.save(jobItemBO);
            return false;
        }
        return true;
    }

    void afterSelectSuccess(String jobNo, long exeStart, long totalCount) {
        DownloadJobBO job = downloadJobService.getByJobNo(jobNo);
        if (ObjectUtil.isNotNull(job)) {
            DownloadJobBO jobUp = new DownloadJobBO();
            jobUp.setId(job.getId());
            jobUp.setJobStatus(JobStatusEnum.ENDED.getCode());
            jobUp.setDownloadTimes(System.currentTimeMillis() - exeStart);
            jobUp.setDownloadTotal(totalCount);
            jobUp.setDownloadEndTime(new Date());
            downloadJobService.updateById(jobUp);
        }
    }

    void afterSelectFail(String jobNo, long exeStart, String selectFailMsg) {
        DownloadJobBO job = downloadJobService.getByJobNo(jobNo);
        if (ObjectUtil.isNotNull(job)) {
            DownloadJobBO jobUp = new DownloadJobBO();
            jobUp.setId(job.getId());
            jobUp.setJobStatus(JobStatusEnum.EXCEPTION.getCode());
            jobUp.setDownloadTimes(System.currentTimeMillis() - exeStart);
            jobUp.setDownloadEndTime(new Date());
            downloadJobService.updateById(jobUp);

            DownloadJobItemBO jobItemBO = new DownloadJobItemBO();
            jobItemBO.setJobId(job.getId());
            jobItemBO.setJobNo(job.getJobNo());
            jobItemBO.setSelectNum(getSelectNumTotal(job.getSelectNumTotal()));
            jobItemBO.setSelectResult(JobSelectResultEnum.FAIL.getCode());
            jobItemBO.setFailMsg(selectFailMsg);
            downloadJobItemService.save(jobItemBO);
        }
    }

    Integer getPageSize(String typeCode) {
        JobTypeEnum jobTypeEnum = JobTypeEnum.getByCode(typeCode);
        if (ObjectUtil.isNotNull(jobTypeEnum) && jobTypeEnum.getSelectLimit() > 0) {
            return jobTypeEnum.getSelectLimit();
        }
        return DownloadConstant.DOWNLOAD_MAX_EACH_SELECT_LIMIT;
    }

    private void fillFileData(String fileName, List<?> list, long offset, JobTypeEnum typeEnum) throws IOException {
        if (ObjectUtil.isNotNull(typeEnum) && BooleanUtil.isTrue(typeEnum.isAutoSheet())) {
            ExcelUtil.exportFileAppendAutoSheet(localFilePath, fileName, list, offset, typeEnum.getSheetLimit(), typeEnum.getSheetName());
        } else {
            ExcelUtil.exportFileAppend(localFilePath, fileName, list, offset);
        }
    }

    private String genJobNo() {
        return IdUtil.getSnowflakeNextIdStr();
    }

    private int getSelectNumTotal(Integer selectNumTotal) {
        if (ObjectUtil.isNull(selectNumTotal))
            return 1;
        return ++selectNumTotal;
    }
}
